package com.ruihang.generalibrary.ui.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.jiongbull.jlog.JLog;
import com.ruihang.generalibrary.ui.util.IAutoLoadMore;
import com.ruihang.generalibrary.ui.util.IAutoLoadMoreConditions;
import com.ruihang.generalibrary.ui.util.OnItemInternalCheckChangedListener;
import com.ruihang.generalibrary.ui.util.OnItemInternalClick;
import com.ruihang.generalibrary.utils.ListUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * recylerview的适配器的基类
 * Created by Ly on 2016/11/30.
 */
public abstract class BaseRecylerAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH>
        implements OnItemInternalClick, OnItemInternalCheckChangedListener {

    protected Context context;
    protected List<T> data;

    protected OnItemInternalClick itemInternalClick;

    protected OnItemInternalCheckChangedListener itemInternalCheckChangedListener;

    protected IAutoLoadMore<T> loadMoreListener;

    protected boolean hasMore = true;//是否还有更多数据

    protected boolean isLoadingMore;//是否正在加载更多

    protected IAutoLoadMoreConditions<T> loadMoreConditions; // 外部的自动加载更多的条件


    //加载的更多的界限
    protected int loadLimitLess = 3;//数据较少时使用，倒数第loadLimitLess条加载更多
    protected int loadLimitMore = 9;//数据较多时使用，loadLimitMore

    protected int moreOrLessLimit = 15;//数据为较多或较少的标准，大于此数使用较多的界限，否则使用较少的界限

    public BaseRecylerAdapter(Context context, List<T> list) {
        this.context = context;
        this.data = new ArrayList<>();
        setData(list);
    }

    @Override
    public int getItemCount() {
        return getDataSize();
    }

    @Override
    public void onViewDetachedFromWindow(VH holder) {
        super.onViewDetachedFromWindow(holder);

    }

    protected int getDataSize() {
        if (data != null) {
            return data.size();
        }
        return 0;
    }

    public BaseRecylerAdapter setData(List<T> data) {
        this.data.clear();
        if (data != null) {
            this.data.addAll(data);
        }
        notifyDataSetChanged();
        return this;
    }

    public BaseRecylerAdapter setDataEx(List<? extends T> data) {
        if (this.data != null) {
            this.data.clear();
        } else {
            this.data = new ArrayList<>();
        }
        this.data.addAll(data);
        notifyDataSetChanged();
        return this;
    }

    public T getItem(int position) {
        if (position >= 0 && position < getItemCount()) {
            return data.get(position);
        }
        return null;
    }

    protected synchronized void callLoadMore(int pos) {
        if (hasMore && !isLoadingMore && loadMoreListener != null) {

            if (matchLoadMore(pos)) {
                isLoadingMore = loadMoreListener.OnAutoLoadMore(this, data);
            }
        }
    }

    protected boolean matchLoadMore(int pos) {
        if (loadMoreConditions != null) {
            if (loadMoreConditions.isOnlyThis()) {
                return loadMoreConditions.matchLoadMore(data, pos);
            } else {
                return loadMoreConditions.matchLoadMore(data, pos) || defaultMatchLoadMore(pos);
            }
        } else {
            return defaultMatchLoadMore(pos);
        }
    }

    protected boolean defaultMatchLoadMore(int pos) {
        int limit = data.size() > moreOrLessLimit ? loadLimitMore : loadLimitLess;
        return pos >= data.size() - limit - 1;//倒数第limit条时加载更多
    }

    public void clean() {
        if (getItemCount() > 0) {
            data.clear();
            notifyDataSetChanged();
        }
    }

    public void addDatas(List<T> list) {
        if (data == null) {
            if (ListUtils.isListValued(list)) {
                data = new ArrayList<>();
                data.addAll(list);
                notifyDataSetChanged();
            }
        } else if (list != null && list.size() > 0) {
            int fromPos = getItemCount();
            if (fromPos < 0) {
                fromPos = 0;
            }
            data.addAll(list);
            notifyItemRangeChanged(fromPos, list.size());
        }
    }

    public void addDatasEx(List<? extends T> list) {
        if (data == null) {
            data = new ArrayList<>();
            data.addAll(list);
            if (ListUtils.isListValued(list)) {
                notifyDataSetChanged();
            }
        } else if (list != null && list.size() > 0) {
            int fromPos = getItemCount();
            if (fromPos < 0) {
                fromPos = 0;
            }
            data.addAll(list);
            notifyItemRangeChanged(fromPos, list.size());
        }
    }

    public int addData(T t) {
        if (t != null) {
            if (data == null) {
                data = new ArrayList<>();
            }
            int insert = data.size();
            data.add(t);
            notifyItemInserted(insert);
            return insert;
        }
        return -1;
    }

    public synchronized int addData(T t, int pos) {
        if (t == null) {
            return -1;
        }
        if (data == null) {
            data = new ArrayList<>();
        }
        int count = data.size();
        if (pos < 0 || pos >= count) {
            pos = count;
            data.add(t);
        } else {
            JLog.e("ADD!!!!!!!!!!!!!!!!!", "pos:" + pos + "  list:" + t.toString());
            data.add(pos, t);
        }
        notifyItemInserted(pos);
        return pos;
    }

    /**
     * 设置数据,单个数据的设置
     *
     * @param t
     * @param pos
     * @param isforceAdd 是否当设置位置超出界限时强制添加
     * @return
     */
    public int setDataInPos(T t, int pos, boolean isforceAdd) {
        if (t == null) {
            return -1;
        }
        int count = getItemCount();
        if (pos < 0 || pos >= count) {
            if (isforceAdd) {
                if (data == null) {
                    data = new ArrayList<>();
                }
                data.add(t);
                notifyItemInserted(count);
                pos = count;
            } else {
                pos = -1;
            }
        } else {
//            JLog.e("SET!!!!!!!!!!!!!!!!!", "pos:" + pos + "  list:" + t.toString());
            data.set(pos, t);
            notifyItemChanged(pos);
        }
        return pos;
    }

    public void resetDatasFrom(int pos, List<T> datas, boolean isForceAdd) {
        if (datas == null || datas.size() == 0) {
            return;
        }
        if (pos < 0) {
            if (isForceAdd) {
                addDatas(datas);
            }
        } else {
            int count = getItemCount();
            if (pos < count) {
                data = data.subList(0, pos);
                JLog.e("after sub size is " + data.size());
                data.addAll(datas);
                notifyItemRangeChanged(pos, Math.max(count - pos, datas.size()));
            } else {
                addDatas(datas);
            }
        }
    }

    public boolean removeByPostion(int pos) {
        if (pos < 0 || pos >= getItemCount()) {
            return false;
        }
        data.remove(pos);
        notifyItemRemoved(pos);
        return true;
    }

    public boolean removeFrom(int pos) {
        if (pos < 0 || pos >= getItemCount()) {
            return false;
        }
        if (pos == 0) {
            clean();
            return true;
        }
        int size = getItemCount() - pos;
        if (size == 1) {
            data.remove(pos);
            notifyItemRemoved(pos);
        } else {
            while (pos < getItemCount()) {
                data.remove(pos);
            }
            notifyItemRangeRemoved(pos, size);
        }
        return true;
    }

    public void onDestory() {
    }

    public void onPause() {
    }

    public void onResume() {
    }

    ;

    public BaseRecylerAdapter<T, VH> setLoadMoreListener(IAutoLoadMore<T> loadMoreListener) {
        this.loadMoreListener = loadMoreListener;
        return this;
    }

    public BaseRecylerAdapter setLoadMoreConditions(IAutoLoadMoreConditions<T> loadMoreConditions) {
        this.loadMoreConditions = loadMoreConditions;
        return this;
    }

    public void setHasMore(boolean hasMore) {
        this.hasMore = hasMore;
    }

    public BaseRecylerAdapter<T, VH> setLoadingMore(boolean loadingMore) {
        isLoadingMore = loadingMore;
        return this;
    }

    public boolean isLoadingMore() {
        return isLoadingMore;
    }

    public BaseRecylerAdapter setItemInternalClick(OnItemInternalClick itemInternalClick) {
        this.itemInternalClick = itemInternalClick;
        return this;
    }

    public BaseRecylerAdapter setItemInternalCheckChangedListener(OnItemInternalCheckChangedListener itemInternalCheckChangedListener) {
        this.itemInternalCheckChangedListener = itemInternalCheckChangedListener;
        return this;
    }

    @Override
    public void onItemInternalClick(View itemView, View view, int position) {
        if (itemInternalClick != null) {
            itemInternalClick.onItemInternalClick(itemView, view, position);
        }
    }

    @Override
    public void onItemInternalCheckedChanged(View itemView, View checkable, int postion, boolean checked) {
        if (itemInternalCheckChangedListener != null) {
            itemInternalCheckChangedListener.onItemInternalCheckedChanged(itemView, checkable, postion, checked);
        }
    }
}
